/*
 * mlx90640_i2c_adapter.c
 *
 *  Created on: Aug 10, 2023
 *	  Author: colourfate
 */
#include "stdio.h"
#include "stdint.h"

#include "mlx90640_adapter.h"
#include "i2c_application.h"

#define MLX90640_I2C_ADDR 0x33
#define TA_SHIFT          8

enum REFRESHRATE {
    FPS2HZ  = 0x02,
    FPS4HZ  = 0x03,
    FPS8HZ  = 0x04,
    FPS16HZ = 0x05,
    FPS32HZ = 0x06
};
#define I2C_FREQ_CONFIG         600000

#define I2C_TO_SERIAL_CMD_PING  0x00
#define I2C_TO_SERIAL_CMD_RESET 0x01
#define I2C_TO_SERIAL_CMD_WRITE 0x02
#define I2C_TO_SERIAL_CMD_READ  0x03
#define I2C_TO_SERIAL_CMD_WAIT  0x04

#define I2C_TO_SERIAL_CMD_MAX   5

void MLX90640_I2CInit(void){};
int MLX90640_I2CGeneralReset(void)
{
    return 0;
};
void MLX90640_I2CFreqSet(int freq){};

extern i2c_handle_type hi2cx;
static i2c_status_type i2c_status;
static uint16_t read_data;
#define I2C_TIMEOUT 0xFFFFFFFF
int MLX90640_I2CRead(uint8_t slaveAddr, uint16_t startAddress, uint16_t nMemAddressRead, uint16_t *data)
{

    uint8_t *bp = (uint8_t *)data;
    // printf("i2c addr:%d\n", slaveAddr);
    if ((i2c_status = i2c_memory_read(&hi2cx, I2C_MEM_ADDR_WIDIH_16, slaveAddr << 1, startAddress, bp, nMemAddressRead * 2, I2C_TIMEOUT)) != I2C_OK) {
        printf("i2c erro:%d\n", i2c_status);
        return -1;
    }
    for (int i = 0; i < nMemAddressRead * 2; i += 2) {
        uint8_t tmp = bp[i + 1];

        bp[i + 1] = bp[i];
        bp[i]     = tmp;
    }

    return 0;
}

int MLX90640_I2CWrite(uint8_t slaveAddr, uint16_t writeAddress, uint16_t data)
{
    uint8_t cmd[2];
    cmd[0] = data >> 8;
    cmd[1] = data & 0x00FF;
    // printf("i2c addr:%d\n", slaveAddr);
    if ((i2c_status = i2c_memory_write(&hi2cx, I2C_MEM_ADDR_WIDIH_16, slaveAddr << 1, writeAddress, cmd, 2, I2C_TIMEOUT)) != I2C_OK) {
        printf("i2c erro:%d\n", i2c_status);
        return -1;
    }
    MLX90640_I2CRead(slaveAddr, writeAddress, 1, &read_data);
    if (read_data != data) {
        return -2;
    }

    return 0;
}
static paramsMLX90640 g_mlx90640_param;
extern uint8_t mlx90640_erro_flag;
void mlx_param_init(void)
{
    int status;
    static uint16_t g_eeMLX90640[832];

    // MX_I2C1_Init();

    status = MLX90640_SetRefreshRate(MLX90640_I2C_ADDR, FPS8HZ);
    if (status != 0) {
        printf("Set refresh rate failed\r\n");
        return;
    }

    status = MLX90640_SetChessMode(MLX90640_I2C_ADDR);
    if (status != 0) {
        printf("Set chess mode failed\r\n");
        return;
    }

    status = MLX90640_DumpEE(MLX90640_I2C_ADDR, g_eeMLX90640);
    if (status != 0) {
        printf("Failed to load system parameters\r\n");
        return;
    }

    printf("dump: \r\n");
    for (int i = 0; i < 16; i++) {
        printf("%d: %x\r\n", i, g_eeMLX90640[i]);
    }
    printf("sizeof(g_mlx90640_param) = %d \r\n", sizeof(g_mlx90640_param));

    status = MLX90640_ExtractParameters(g_eeMLX90640, &g_mlx90640_param);
    if (status != 0) {
        printf("Parameter extraction failed: %d\r\n", status);
        return;
    }
    mlx90640_erro_flag = 1;
    printf("MLX90640 ok\r\n");
}

void mlx_data_read(float data[MLX90640_PIXEL_NUM])
{
    // uint32_t start;

    // Read both subpages
    for (int x = 0; x < 2; x++) {
        static uint16_t g_mlx90640Frame[834];
        int status;

        // start = HAL_GetTick();
        status = MLX90640_GetFrameData(MLX90640_I2C_ADDR, g_mlx90640Frame);
        if (status < 0) {
            printf("GetFrame Error: %d\r\n", status);
        }
        // pinfo("get frame: %ld\r\n", HAL_GetTick() - start);

        //float vdd = MLX90640_GetVdd(g_mlx90640Frame, &g_mlx90640_param);
        float Ta  = MLX90640_GetTa(g_mlx90640Frame, &g_mlx90640_param);

        float tr         = Ta - TA_SHIFT; // Reflected temperature based on the sensor ambient temperature
        float emissivity = 0.95;
        // start = HAL_GetTick();
        MLX90640_CalculateTo(g_mlx90640Frame, &g_mlx90640_param, emissivity, tr, data);
        // pinfo("calculate: %ld\r\n", HAL_GetTick() - start);
    }
}
#include "usb_data_transfer.h"
extern uint8_t g_receive_ok;
extern usb_control_cmd g_usb_cmd;
int mlx_set_refresh_rate()
{
    if (g_receive_ok==0){
        return -1;
    }
    g_receive_ok = 0;
    enum REFRESHRATE refresh_cfg;
    int status;

    if (g_usb_cmd.fps == 4) {
        refresh_cfg = FPS8HZ;
    } else if (g_usb_cmd.fps== 8) {
        refresh_cfg = FPS16HZ;
    } else {
        printf("Not support fps: %d\r\n", g_usb_cmd.fps);
        return -1;
    }

    // Subpage fresh rate
    status = MLX90640_SetRefreshRate(MLX90640_I2C_ADDR, refresh_cfg);
    if (status != 0) {
        printf("Set refresh rate failed: %d\r\n", status);
        return -1;
    }

    return 0;
}
